package com.own.component.common.util.list;

import com.alibaba.fastjson2.JSON;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * ListSortUtil
 *
 * @author chenxueli
 * @target 支持多层级的排序，同层级数据自定义排序
 * @date 2023-03-21 16:40:00
 */
@Slf4j
public class ListSortUtil {

    /**
     * 混合排序器
     *
     * @param list       需要排序的列表
     * @param methodList 排序方法列表
     * @param <T>        项目类型
     * @param <R>        排序键类型
     * @param <U>        比较键类型
     * @return 排序后的列表
     */
    @SafeVarargs
    public static <T, R, U extends Comparable<? super U>> List<T> hybrid(
            List<T> list,
            HybridSortMethod<T, R, U>... methodList
    ) {
        if (list == null || list.isEmpty()) {
            return list;
        }
        return list.stream().sorted((x, y) -> compare(x, y, methodList)).collect(Collectors.toList());
    }

    /**
     * 执行排序
     *
     * @param item1      项目1
     * @param item2      项目2
     * @param methodList 排序方法列表
     * @param <T>        项目类型
     * @param <R>        排序键类型
     * @return 比较结果
     */
    @SafeVarargs
    private static <T, R, U extends Comparable<? super U>> int compare(T item1, T item2, HybridSortMethod<T, R, U>... methodList) {
        for (var method : methodList) {
            if (method.keyList != null) {
                var keyList = method.keyList;
                // 获取对应的值
                var value1 = method.extractor.apply(item1);
                var value2 = method.extractor.apply(item2);
                var index1 = keyList.indexOf(value1);
                var index2 = keyList.indexOf(value2);
                // 进行有序序列的比较
                var compare = Integer.compare(index1, index2);
                // 如果相等则继续比较下一个
                if (compare == 0) {
                    continue;
                }
                return compare;
            }
            if (method.keyExtractor != null) {
                var compare = method.keyExtractor.apply(item1).compareTo(method.keyExtractor.apply(item2));
                // 如果相等则继续比较下一个
                if (compare == 0) {
                    continue;
                }
                return compare;
            }
        }
        return 0;
    }

    public static void main(String[] args) {
        var list = new ArrayList<TestUser>();
        list.add(new TestUser("张三", 18));
        list.add(new TestUser("李四", 20));
        list.add(new TestUser("王五", 19));
        list.add(new TestUser("赵六", 18));
        list.add(new TestUser("田七", 20));
        list.add(new TestUser("孙八", 18));
        // 执行排血
        var resultList = hybrid(
                list,
                HybridSortMethod.<TestUser, String, Integer>builder()
                        .keyExtractor(TestUser::getAge)
                        .build(),
                HybridSortMethod.<TestUser, String, Integer>builder()
                        .extractor(TestUser::getName)
                        .keyList(List.of("李四", "赵六", "王五", "田七", "孙八", "张三"))
                        .build()
        );
        System.out.println("JSON.toJSONString(resultList) = " + JSON.toJSONString(resultList));


    }

    @Builder
    public static class HybridSortMethod<T, R, U extends Comparable<? super U>> {
        /**
         * 排序key
         */
        @Builder.Default
        private List<R> keyList = null;
        /**
         * 需要排序的字段
         */
        @Builder.Default
        private Function<T, R> extractor = null;
        /**
         * 比较方法
         */
        @Builder.Default
        private Function<? super T, ? extends U> keyExtractor = null;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class TestUser {
        private String name;
        private Integer age;
    }

}
